package com.solo.game.snake;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class SnakeFrame extends JFrame implements FocusListener {

    /**
     * 
     */
    private static final long serialVersionUID = -1681388098767984670L;

    // 菜单栏
    private JMenuBar menuBar;

    // 游戏面板
    private JPanel gamePanel;

    // 信息面板
    private JPanel infoPanel;
    
    // 配置框
    private JFrame settingFrame;
    
    // 配置
    private Preference preference;
    
    private JButton[][] matrix;
    
    // 一局游戏
    private Game game;

    public SnakeFrame() {

        initMenu();

        gamePanel = new JPanel();
        infoPanel = new JPanel();
        JLabel title = new JLabel("贪吃蛇xxxxxxxxxxxxxxx");
        title.setSize(200, 20);
        title.setBackground(Color.GREEN);
        infoPanel.add(title);
        // 获取配置
        this.preference = Preference.load();
        initGameField(preference);
        setupKeyboard();
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(gamePanel, BorderLayout.CENTER);
        
        this.getContentPane().add(infoPanel, BorderLayout.EAST);
        
//        
//        infoPanel.setSize(100, gamePanel.getHeight());
//        infoPanel.setBackground(Color.yellow);
//        this.add(infoPanel, BorderLayout.EAST);

//        this.setSize(gamePanel.getWidth() + infoPanel.getWidth(), gamePanel
//                .getHeight()+60);
    }

    /**
     * 
     * <P>描述: 初始化配置框
     * 
     * @author Zangrong.Solo
     * 日期: Dec 14, 2012 9:50:25 AM
     */
    private void initSettingFrame() {
        Dimension d = new Dimension(400, 200);
        settingFrame = new JFrame();
        
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.setSize(d);
        
        initEnvSetting(d, tabbedPane);
        
        JPanel controlPanel = new JPanel();
        controlPanel.setSize(d);
        tabbedPane.addTab("操作设定", controlPanel);
        
        JPanel modePanel = new JPanel();
        modePanel.setSize(d);
        tabbedPane.addTab("游戏设定", modePanel);
        
        settingFrame.add(tabbedPane);
        settingFrame.setSize(d);
        
        Point location = this.getLocation();
        settingFrame.setLocation((int)location.getX()+ this.getWidth(), (int)location.getY());
        settingFrame.setVisible(true);
        
    }

    private void initEnvSetting(Dimension d, JTabbedPane tabbedPane) {

        JPanel envPanel = new JPanel();
        envPanel.setSize(d);
        tabbedPane.addTab("环境设定", envPanel);
        
        JLabel rowLabel = new JLabel("行");
        final JTextField rowField = new JTextField();
        rowField.setText(this.preference.getRow()+"");
        rowField.setColumns(3);
        
        JLabel columnLabel = new JLabel("列");
        final JTextField columnField = new JTextField();
        columnField.setText(this.preference.getColumn()+"");
        columnField.setColumns(3);

        JLabel lengthLabel = new JLabel("边长");
        final JTextField lengthField = new JTextField();
        lengthField.setText(this.preference.getLength()+"");
        lengthField.setColumns(3);
        
        JButton applyBtn = new JButton("应用");
        applyBtn.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                int row = Integer.parseInt(rowField.getText());
                int col = Integer.parseInt(columnField.getText());
                int length = Integer.parseInt(lengthField.getText());
                preference.setRow(row);
                preference.setColumn(col);
                preference.setLength(length);
                Preference.save(preference);
                initGameField(preference);
            }
            
        });
        
        envPanel.add(rowLabel);
        envPanel.add(rowField);
        envPanel.add(columnLabel);
        envPanel.add(columnField);
        envPanel.add(lengthLabel);
        envPanel.add(lengthField);
        envPanel.add(applyBtn);
    }

    /**
     * 初始化界面
     * 
     * @param pref
     * 
     */
    private void initGameField(Preference pref) {
        int row = pref.getRow();
        int col = pref.getColumn();
        int length = pref.getLength();
        matrix = new JButton[row][col];
        // 刷新组件需要先removeAll，再validate
        gamePanel.removeAll();
        gamePanel.setLayout(new GridLayout(row, col));
        gamePanel.setSize(col * length, row * length);

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                matrix[i][j] = new JButton();
                matrix[i][j].setBackground(pref.getGroundColor());
                gamePanel.add(matrix[i][j]);
            }
        }
        game = new Game(matrix, pref);
        gamePanel.validate();
        infoPanel.setSize(200, gamePanel.getHeight());
        this.setSize(gamePanel.getWidth() + infoPanel.getWidth(), gamePanel
                .getHeight());
        System.out.println(gamePanel.getWidth() + "," + gamePanel.getHeight());
        System.out.println(infoPanel.getWidth() + "," + infoPanel.getHeight());
        System.out.println(this.getWidth() + "," + this.getHeight());
        this.setResizable(false);
    }
    
    /**
     * 
     * <P>
     * 描述: 初始化菜单
     * 
     * @author Zangrong.Solo 日期: Dec 14, 2012 9:41:08 AM
     */
    private void initMenu() {

        menuBar = new JMenuBar();
        
        JMenu startMenu = new JMenu("开始");
        menuBar.add(startMenu);
        
        JMenu settingMenu = new JMenu("配置");
        menuBar.add(settingMenu);
        JMenuItem item = new JMenuItem("设定");
        settingMenu.add(item);
        item.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                if (settingFrame == null) {
                    initSettingFrame();
                } else {
                    settingFrame.setVisible(true);
                }
            }
            
        });
        
        JMenu aboutMenu = new JMenu("关于");
        aboutMenu.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(SnakeFrame.this.getHeight());
            }
            
        });
        menuBar.add(aboutMenu);
        this.setJMenuBar(menuBar);
    }
    
    private void setAction(String action)
    {
        if (game != null) {
            game.setAction(action);
        }
    }
    
    private void modifyGameState()
    {
        if (game != null) {
            game.modifyGameState();
        }
    }
    
    /**
     * 捆绑键盘事件
     */
    private void setupKeyboard() {
        InputMap input = this.gamePanel
                .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        input.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), Action.ACTION_KEY_LEFT);
        input.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), Action.ACTION_KEY_RIGHT);
        input.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), Action.ACTION_KEY_UP);
        input.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), Action.ACTION_KEY_DOWN);
        input.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), Action.KEY_CONTROL);
        ActionMap actionMap = this.gamePanel.getActionMap();
        actionMap.put(Action.ACTION_KEY_LEFT, new AbstractAction()
        // 动作限制可以放到线程里面去
                {
                    /**
                     * 
                     */
                    private static final long serialVersionUID = 1L;

                    public void actionPerformed(ActionEvent e) {
                        setAction(Action.ACTION_KEY_LEFT);
                    }
                });
        actionMap.put(Action.ACTION_KEY_RIGHT, new AbstractAction() {
            /**
             * 
             */
            private static final long serialVersionUID = -5280182173040571406L;

            public void actionPerformed(ActionEvent e) {
                setAction(Action.ACTION_KEY_RIGHT);
            }
        });
        actionMap.put(Action.ACTION_KEY_UP, new AbstractAction() {
            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                setAction(Action.ACTION_KEY_UP);
            }
        });
        actionMap.put(Action.ACTION_KEY_DOWN, new AbstractAction() {
            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                setAction(Action.ACTION_KEY_DOWN);
            }
        });
        
        actionMap.put(Action.KEY_CONTROL, new AbstractAction() {
            /**
             * 
             */
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                modifyGameState();
            }
        });
    }

    @Override
    public void focusGained(FocusEvent e) {
        // TODO 什么也不做
    }

    @Override
    public void focusLost(FocusEvent e) {
        if (this.game != null) {
            // 如果当前不是停止状态，则把游戏状态置为暂停状态
            if (!Game.GAME_STATE_STOP.equals(this.game.getState())) {
                this.game.setState(Game.GAME_STATE_SUSPEND);
            }
        }
    }
}
